package com.globox.servlet;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import utils.Sit;

public class ReserveSits extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = -2608993166275913759L;
	private static final String ADD_RESERVATION = app_srv_interface.IGlobox.ADD_RESERVATION;
	private static final String BROWSE_SITS_THEATERS = app_srv_interface.IGlobox.BROWSE_SITS_THEATER;
	private static final String OK = app_srv_interface.IGlobox.OK;

	private String appSrvPort = IConstants.appSrvPort;
	private String appSrvHost = IConstants.appSrvHost;

	private Integer clientID = -1;

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// same logic
		this.doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// Use "request" to read incoming HTTP headers (e.g. cookies)
		// and HTML form data (e.g. data the user entered and submitted)

		// Use "response" to specify the HTTP response line and headers
		// (e.g. specifying the content type, setting cookies).

		HttpSession session = request.getSession(true);
		if (session != null) {
			clientID = (Integer) session.getAttribute("MY_UNIQUE_ID");
			if (clientID < 0) {
				// regenerate
				clientID = new Random().nextInt(IConstants.MAX_CLIENTS);
				session.setAttribute("MY_UNIQUE_ID", clientID);
			}
		} else {
			Random rnd = new Random();
			clientID = rnd.nextInt(IConstants.MAX_CLIENTS);
		}

		String header = IConstants.HEADER;
		header = header.replace("{{uniqueId}}", clientID + "");

		PrintWriter out = response.getWriter();
		String t = request.getParameter("theaterHF");
		if (t == null)
			t = request.getParameter("theater");
		String sits = request.getParameter("allReservedSitsHF");
		sits = sits.trim();
		t = t.trim();
		// out.write("t:" + t);
		// out.write("sits:" + sits);
		// String qs = request.getQueryString();
		// String[] ands = qs.split("&");

		// for (int i = 0; i < ands.length; i++) {
		// String[] eqs = ands[i].split("=");
		// sits += eqs[0] + ";";
		// }

		// my reserved sits section
		String myReservedSit = "";
		String myPurchasedSit = "";
		String reserSit = "", purchSit = "";
		String automReservSeat = "";

		// out.write("sits==" + sits + "<br />");

		if (sits != null && !sits.equalsIgnoreCase("") && t != null
				&& !t.equalsIgnoreCase("")) {

			// construct the sits to be reserved and send them
			try {
				String headerInfo = "<p style=\"background-color:yellow; color:black; font-weight:bold\">Last reserved sits: ";
				List<Sit> all = new ArrayList<Sit>();

				if (sits.indexOf(';') != -1) {
					String[] allArray = sits.split(";");
					for (String s : allArray) {
						if (!s.equalsIgnoreCase("")) {
							Sit sit = new Sit(s);
							sit.setOcupied(true);
							all.add(sit);
							headerInfo += sit.getNumber() + " ";
						}
					}
				} else {// one sit only
					if (!sits.equalsIgnoreCase("")) {
						Sit sit = new Sit(sits);
						sit.setOcupied(true);
						all.add(sit);
						headerInfo += sit.getNumber();
					}
				}

				headerInfo += "</p>";

				List<Sit> theSits = addReservation(t, all);

				if (theSits != null && theSits.size() > 0) {

					try {

						if (theSits != null && theSits.size() > 0) {

							// first build sections my reserved and my purchased
							// sits
							for (Sit s : theSits) {
								if (s.isReserved()
										&& s.geOccupiedBy() != null
										&& s.geOccupiedBy().equalsIgnoreCase(
												clientID + ""))
									reserSit += s.getNumber() + " ";
								if (s.isOccupied()
										&& s.geOccupiedBy() != null
										&& s.geOccupiedBy().equalsIgnoreCase(
												clientID + ""))
									purchSit += s.getNumber() + " ";
							}

							if (!reserSit.equalsIgnoreCase("")) {
								myReservedSit = "<p style=\"align:right;background-color:black; color:orange; font-weight:bold;\">The following sits "
										+ reserSit
										+ " are reserved for you. You can reserve a sit by clicking on it, or select more sits and click next button to reserve them!</p>";
								automReservSeat = reserSit.trim();
								// update hidden field by forcing a btn click
								myReservedSit += "<input type='button' style=\"visibility:hidden;\" id='invBtn' name='invBtn' value='go go' onclick=\"updateHF('"
										+ automReservSeat + "');\" />";
							} else
								myReservedSit = "<p style=\"align:right; background-color:black; color:orange; font-weight:bold;\">You have no sits reserved for the momment</p>";

							if (!purchSit.equalsIgnoreCase("")) {
								myPurchasedSit = "<p style=\"align:right;color:green;font-weight:bold;\">The following sits "
										+ reserSit
										+ " are purchased by you.</p>";
							} else
								myPurchasedSit = "<p style=\"align:right;color:green;font-weight:bold;\">You have no sits purchased for the momment</p>";

							String output = header
									+ myPurchasedSit
									+ myReservedSit
									+ "<p style=\"background-color:black; color:white\">Sits for theater ( "
									+ t
									+ " )"
									+ "</p>"
									+ headerInfo
									+ "<form name=\"purchaseStep\" method=\"POST\" action=\"/globox-client/purchase-sits"
									+ "\"><table cellspacing=\"10\" cellpadding=\"10\"><tr>";

							int i = 0;
							for (Sit s : theSits) {
								if (i % 10 == 0 && i > 0) {
									output += "</tr>";
								} else {
									String color = s.isOccupied() ? "red" : s
											.isReserved() ? "blue" : "green";
									String state = color
											.equalsIgnoreCase("red") ? "occupied"
											: color.equals("blue") ? "reserved"
													: "free: " + s.getNumber();
									String href = (state
											.equalsIgnoreCase("occupied") || state
											.equalsIgnoreCase("reserved")) ? ""
											: "href=/globox-client/reserve-sits?theater="
													+ t;
									if (!href.equalsIgnoreCase("")) {
										href += "&allReservedSitsHF="
												+ s.getNumber()
												+ " onClick=\"ReserveSit("
												+ s.getNumber() + ")\"";
									} else
										href = "\"";
									String title = "";
									title = (state.equalsIgnoreCase("reserved")) ? "This sit is reserved"
											+ ((s.geOccupiedBy() != null && s
													.geOccupiedBy()
													.equalsIgnoreCase(
															clientID + "")) ? " by you"
													: "")
											: (state.equalsIgnoreCase("occupied")) ? "This sit is occupied"
													+ ((s.geOccupiedBy() != null && s
															.geOccupiedBy()
															.equalsIgnoreCase(
																	clientID
																			+ "")) ? " by you"
															: "")
													: "Reserve this sit:"
															+ s.getNumber();

									String link = "<a " + href
											+ " style=\"color:" + color
											+ "\" title=\"" + title + "\">"
											+ s.getNumber() + "</a>";
									String cb = "<input type=\"checkbox\" name=\""
											+ s.getNumber()
											+ "\" onClick=\"addReservedSit(this,this.value);\" value=\""
											+ s.getNumber()
											+ "\" title=\"This sit is "
											+ state
											+ "\"" + " />";

									output += "<td>" + link + "</td><td>";

									if (!s.isOccupied() && !s.isReserved()) {
										output += cb + "</td>";
									} else
										output += "</td>";
								}

								i++;
							}

							output += "</table>";
							output += "<input type=\"hidden\" id=\"allReservedSitsHF\" name=\"allReservedSitsHF\" value=\""
									+ sits + "\" />";
							output += "<input type=\"hidden\" id=\"theaterHF\" name=\"theaterHF\" value=\""
									+ t + "\" />";
							output += "<script>updateHF('" + automReservSeat
									+ "');</script>";
							output += "<p>Click next to finalize purchase</p>";

							String purchaseBtn = "<input type=\"submit\" value=\"++Purchase++\" />";

							output += purchaseBtn + "</form></body></html>";

							out.write(output);

						} else {
							out.write(header
									+ "<p style=\"color:red; font-weight:bold;\">The server processed your request, but failed to retreive the sits after.</p><br />");
						}
					} catch (NumberFormatException e) {
						out.write("NumberFormatException parsing app srv port."
								+ e + "<br />");
						e.printStackTrace();
					} catch (Exception e) {
						out.write("Exception " + e + "<br />");
						e.printStackTrace();
					}

					// redirect
					// response.sendRedirect("/globox-client/browse-sits?theater="
					// + t);
					// RequestDispatcher dispatcher = request
					// .getRequestDispatcher(response.toString());
					// dispatcher.forward(request, response);
				} else {
					out.write(header
							+ "<p style=\"color:red; font-weight:bold;\">The server processed your request, but with some errors. Try again please.</p><br />");
				}
			} catch (NumberFormatException e) {
				out.write("NumberFormatException parsing app srv port." + e
						+ "<br />");
				e.printStackTrace();
			} catch (UnknownHostException e) {
				out.write("UnknownHostException connecting to app srv." + e
						+ "<br />");
				e.printStackTrace();
			} catch (IOException e) {
				out.write("IOException in communication with app srv port." + e
						+ "<br />");
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				out.write("ClassNotFoundException in communication with app srv port."
						+ e + "<br />");
				e.printStackTrace();
			} catch (Exception e) {
				out.write("Exception " + e + "<br />");
				e.printStackTrace();
			}
		} else {
			out.write(header
					+ "<script language=\"javascript\">alert('You have to select at least 1 sit!')</script>");
			return;
		}
	}

	private List<Sit> getSitsByTheater(String query, PrintWriter out)
			throws Exception {

		if (!appSrvHost.equalsIgnoreCase("")
				&& !appSrvPort.equalsIgnoreCase("")) {

			Socket s = new Socket(appSrvHost, Integer.parseInt(appSrvPort));

			ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
			ObjectInputStream ois = new ObjectInputStream(s.getInputStream());

			oos.writeObject(BROWSE_SITS_THEATERS);
			oos.flush();

			oos.writeObject(clientID);
			oos.flush();

			oos.writeObject(query);
			oos.flush();

			// out.write("before getting response" + "<br />");

			@SuppressWarnings("unchecked")
			List<Sit> results = (List<Sit>) ois.readObject();

			// out.write("after getting response" + "<br />");
			try {
				ois.close();
				oos.close();
				s.close();
			} catch (Exception e) {
				e.printStackTrace();
			}

			return results;
		} else {
			throw new Exception("Invalid settings-call for server");
		}
	}

	/**
	 * for now we don't use the class reservation
	 */
	private List<Sit> addReservation(String theater, List<Sit> sits)
			throws Exception {

		if (!appSrvHost.equalsIgnoreCase("")
				&& !appSrvPort.equalsIgnoreCase("")) {

			Socket s = new Socket(appSrvHost, Integer.parseInt(appSrvPort));

			ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
			ObjectInputStream ois = new ObjectInputStream(s.getInputStream());

			oos.writeObject(ADD_RESERVATION);
			oos.flush();

			oos.writeObject(clientID);
			oos.flush();

			oos.writeObject(theater);
			oos.flush();

			oos.writeObject(sits);
			oos.flush();

			// read back the new theater seats map

			@SuppressWarnings("unchecked")
			List<Sit> result = (List<Sit>) ois.readObject();

			try {
				ois.close();
				oos.close();
				s.close();
			} catch (Exception e) {
				e.printStackTrace();
			}

			return result;
		} else {
			throw new Exception("Invalid settings-call for server");
		}
	}
}
